from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

import os
import sys
if __package__ is None or __package__ == "":
    # Allow absolute 'api.*' imports when running this file directly (python api/app.py)
    sys.path.append(os.path.dirname(os.path.dirname(__file__)))

from api.routers import flows_controller as flows, runs_controller as runs, nodes_controller as nodes
from api.utils import register_exception_handlers, generate_openapi_json
from api.dao import init_db
from api.managers.kafka_manager import KAFKA_MANAGER
import asyncio
import uvicorn
from api.services.binlog_service import binlog_handler
from api.services.kafka_service import kafka_consumer_task_by_binding
from contextlib import asynccontextmanager
from api.config.kafka_config import get_kafka_settings

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Initialize DB
    init_db()
    # Export OpenAPI JSON
    generate_openapi_json(app)
    # Optional startup log
    print("[Startup] FastAPI app initialized. Routers: flows, runs")

    # Kafka startup controlled via centralized settings
    settings = get_kafka_settings()
    if settings.binder.enabled:
        # Start Kafka binlog consumer on binding 'binlog-db'
        try:
            task_factory = kafka_consumer_task_by_binding("binlog-db", binlog_handler)
            app.state.binlog_consumer_task = asyncio.create_task(task_factory())
            print("[Startup] Kafka binlog consumer started (binding='binlog-db')")
        except Exception as e:
            print(f"[Startup] Kafka binlog consumer failed to start: {e}")
    else:
        print("[Startup] Kafka disabled via KAFKA_ENABLED=false; skipping consumer startup")

    # Yield to allow the app to run
    yield

    # Shutdown: gracefully close Kafka resources
    await KAFKA_MANAGER.close()

app = FastAPI(title="Flow Engine Orchestration API", version="0.1.0", lifespan=lifespan)

# CORS
app.add_middleware(
    CORSMiddleware,
    allow_origin_regex=".*",  # allow any origin and reflect it back (safe with credentials)
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
    expose_headers=["*"],
    max_age=86400,
)

# Register global exception handlers
register_exception_handlers(app)

# Routers
app.include_router(flows.router)
app.include_router(runs.router)
app.include_router(nodes.router)


if __name__ == "__main__":
    uvicorn.run("api.app:app", host="0.0.0.0", port=8000, reload=True)